package oracle.apps.financials.collection.adapter;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import oracle.apps.financials.collection.po.Customer;
import oracle.apps.financials.collection.po.MetricsItemValueHolder;
import oracle.apps.financials.collection.po.RendererValueHolder;
import oracle.apps.financials.collection.util.ChartHelper;
import oracle.apps.financials.collection.util.MockDataFactory;

import org.achartengine.ChartFactory;
import org.achartengine.GraphicalView;
import org.achartengine.chart.BarChart;
import org.achartengine.chart.LineChart;
import org.achartengine.chart.PointStyle;
import org.achartengine.chart.TimeChart;
import org.achartengine.model.XYMultipleSeriesDataset;
import org.achartengine.renderer.XYMultipleSeriesRenderer;
import org.achartengine.tools.TimeSliderRangeListener;

import android.animation.AnimatorSet;
import android.animation.TypeEvaluator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Color;
import android.graphics.Paint.Align;
import android.view.ViewGroup;
import android.widget.LinearLayout;

import com.cyrilmottier.android.greendroid.R;

public class DSOAdapter {
	private Customer customer;
	private Context context;
	private double xMin, xMax, currentX;
	private boolean showDSOBestPossibleGraph = false;
	private boolean showDSOForAllGraph = false;
	private boolean showDSOForPriorPeriodGraph = false;
	private boolean showNoOfCollectorsGraph = false;

	protected GraphicalView lineChart;
	protected GraphicalView timeSliderChart;
	public ViewGroup graphViewGroup;
	protected LinearLayout lineChartLayout;
	protected LinearLayout timeSliderLayout;
	protected TimeSliderRangeListener mOnRangeChangeListner;

	public DSOAdapter(Context context, Customer customer, ViewGroup graphViewGroup) {
		this.context = context;
		this.customer = customer;
		this.xMax = new Date().getTime();
		this.xMin = MockDataFactory.getTime(new Date(), Calendar.MONTH, -3).getTime();
		this.graphViewGroup = graphViewGroup;
		if (this.customer != null) {
			initGraphView();

			mOnRangeChangeListner = new TimeSliderRangeListener() {
				@Override
				public void onRangeChanged(double start, double end) {
					setXAxisRange(lineChart, start, end);
				}
			};

			timeSliderChart.setTimeSliderRangeListener(mOnRangeChangeListner);

		}
	}

	public void setXAxisRange(final GraphicalView mView, double start, double end) {
		xMax = end;
		xMin = start;

		TypeEvaluator mDoubleTypeEvaluator = new TypeEvaluator<Double>() {
			@Override
			public Double evaluate(float fraction, Double startValue, Double endValue) {
				return (fraction * (endValue - startValue) + startValue);
			}

		};
		if (mView.getRenderer() instanceof XYMultipleSeriesRenderer) {

			ValueAnimator.AnimatorUpdateListener animStartUpdateListener = new ValueAnimator.AnimatorUpdateListener() {

				@Override
				public void onAnimationUpdate(ValueAnimator animation) {
					((XYMultipleSeriesRenderer) mView.getRenderer()).setXAxisMin((Double) animation.getAnimatedValue());
					if (((XYMultipleSeriesRenderer) mView.getRenderer()).getScalesCount() > 1) {
						((XYMultipleSeriesRenderer) mView.getRenderer()).setXAxisMin((Double) animation.getAnimatedValue(), 1);
					}
					// ((LineChart)mView.getChart()).getLineSlider().jumpToNearestPoint();
					// Log.d("DSOAdapter",
					// "Value of start1: "+animation.getAnimatedValue());
					// mView.postInvalidate();
				}
			};
			ValueAnimator.AnimatorUpdateListener animEndUpdateListener = new ValueAnimator.AnimatorUpdateListener() {

				@Override
				public void onAnimationUpdate(ValueAnimator animation) {
					((XYMultipleSeriesRenderer) mView.getRenderer()).setXAxisMax((Double) animation.getAnimatedValue());
					if (((XYMultipleSeriesRenderer) mView.getRenderer()).getScalesCount() > 1) {
						((XYMultipleSeriesRenderer) mView.getRenderer()).setXAxisMax((Double) animation.getAnimatedValue(), 1);
					}
					// ((LineChart)mView.getChart()).getLineSlider().jumpToNearestPoint();
					// Log.d("DSOAdapter",
					// "Value of end1: "+animation.getAnimatedValue());
					mView.postInvalidate();
				}
			};
			AnimatorSet animSet = new AnimatorSet();
			ValueAnimator vAnimStart = ValueAnimator.ofObject(mDoubleTypeEvaluator, ((XYMultipleSeriesRenderer) mView.getRenderer()).getXAxisMin(),
					start);
			ValueAnimator vAnimEnd = ValueAnimator
					.ofObject(mDoubleTypeEvaluator, ((XYMultipleSeriesRenderer) mView.getRenderer()).getXAxisMax(), end);
			vAnimStart.addUpdateListener(animStartUpdateListener);
			vAnimEnd.addUpdateListener(animEndUpdateListener);
			vAnimStart.setDuration(1000);
			vAnimEnd.setDuration(1000);
			// animSet.setDuration(10000);

			animSet.playTogether(vAnimStart, vAnimEnd);
			animSet.start();
		}
	}

	public void initGraphView() {

		lineChartLayout = (LinearLayout) graphViewGroup.findViewById(R.id.line_chart);
		timeSliderLayout = (LinearLayout) graphViewGroup.findViewById(R.id.time_slider_chart);

		this.lineChart = getLineOrCombinedChart();
		this.timeSliderChart = getTimeSlideChart();

		timeSliderLayout.removeAllViews();
		lineChartLayout.removeAllViews();

		lineChartLayout.addView(lineChart);
		timeSliderLayout.addView(timeSliderChart);
	}

	public void refreshData(Customer customer) {
		this.customer = customer;
		this.notifyDataSetChanged();
	}

	public void notifyDataSetChanged() {

		MetricsItemValueHolder dso = this.customer.getMetrics().getDSO();

		refreshLineOrCombinedChart(dso);

		refreshTimeSliderChart(dso);

	}

	public void notifyLineOrCombinedChartDataSetChanged() {

		MetricsItemValueHolder dso = this.customer.getMetrics().getDSO();

	}

	public GraphicalView getLineOrCombinedChart() {

		MetricsItemValueHolder dso = this.customer.getMetrics().getDSO();
		RendererValueHolder rendererValue = getLineRendererValue(dso, "LINE");
		rendererValue.setxMax(xMax);
		rendererValue.setxMin(xMin);
		if (rendererValue.getTypes().contains(BarChart.TYPE)) {
			XYMultipleSeriesRenderer renderer = ChartHelper.getChartSettingsCombinedChart(rendererValue);
			renderer.setLineSliderEnabled(true);
			renderer.setYAxisAlign(Align.LEFT, 0);
			renderer.setYAxisAlign(Align.RIGHT, 1);
			return ChartFactory.getCombinedXYChartView(context, (XYMultipleSeriesDataset) ChartHelper.buildCombinedDateDataset(rendererValue),
					renderer, rendererValue.getTypes().toArray(new String[0]), "MM/dd/yyyy");
		} else {
			XYMultipleSeriesRenderer renderer = ChartHelper.getChartSettingsForLineChart(rendererValue);
			return ChartFactory.getTimeChartView(context, ChartHelper.buildDateDataset(rendererValue), renderer, "yyyy/MM/dd");
		}
	}

	public void refreshLineOrCombinedChart(MetricsItemValueHolder dso) {

		RendererValueHolder rendererValue = getLineRendererValue(dso, "LINE");
		rendererValue.setxMax(xMax);
		rendererValue.setxMin(xMin);
		if (!(rendererValue.getTypes().contains(BarChart.TYPE)) && lineChart.getChart() instanceof LineChart) {
			XYMultipleSeriesRenderer renderer = ChartHelper.getChartSettingsForLineChart(rendererValue);
			this.lineChart.DataSetChanged(renderer, ChartHelper.buildDateDataset(rendererValue));
		} else {
			lineChart = getLineOrCombinedChart();
			lineChartLayout.removeAllViews();
			lineChartLayout.addView(lineChart);
		}
	}

	public GraphicalView getTimeSlideChart() {
		MetricsItemValueHolder dso = this.customer.getMetrics().getDSO();
		RendererValueHolder rendererValue = getLineRendererValue(dso, "TIME SLIDER");
		ArrayList<Date> dsoX = (ArrayList<Date>) dso.getxValueList().get(0);
		rendererValue.setxMax(dsoX.get(dsoX.size() - 1).getTime());
		rendererValue.setxMin(dsoX.get(0).getTime());
		XYMultipleSeriesRenderer renderer = ChartHelper.getChartSettingsForTimeSlider(rendererValue);
		XYMultipleSeriesDataset seriesDataset = ChartHelper.buildDateDataset(rendererValue);
		return ChartFactory.getTimeChartView(context, seriesDataset, renderer, "MMM yyyy");
	}

	public void refreshTimeSliderChart(MetricsItemValueHolder dso) {
		RendererValueHolder rendererValue = getLineRendererValue(dso, "TIME SLIDER");
		List<Date> dsoX = (List<Date>) dso.getxValueList().get(0);
		rendererValue.setxMax(dsoX.get(dsoX.size() - 1).getTime());
		rendererValue.setxMin(dsoX.get(0).getTime());
		XYMultipleSeriesRenderer renderer = ChartHelper.getChartSettingsForTimeSlider(rendererValue);
		this.timeSliderChart.DataSetChanged(renderer, ChartHelper.buildDateDataset(rendererValue));
	}

	public RendererValueHolder getLineRendererValue(MetricsItemValueHolder dso, String type) {

		RendererValueHolder rendererValue = new RendererValueHolder(context);
		rendererValue.setChartTitle("Day Sales OutStanding");
		rendererValue.setxTitle("Period");
		rendererValue.setyTitle("Days");

		rendererValue.setyMin(0);
		rendererValue.setyMax(60);
		rendererValue.getyMinList().add(0.00);
		rendererValue.getyMaxList().add(60.00);
		rendererValue.setyLabelMarginTop(30);
		rendererValue.setxLegendMarginLeft(0.1f);

		rendererValue.setAxesColor(Color.BLACK);
		rendererValue.setLabelsColor(Color.BLACK);

		rendererValue.getTitles().add("Day Sales Outstanding");
		rendererValue.getSliderTextList().add("As of ");
		rendererValue.getSliderTextList().add("DSO: ");
		rendererValue.getPointStyles().add(PointStyle.POINT);
		rendererValue.setShowChartTitle(false);

		if (!dso.getxValueList().isEmpty()) {
			rendererValue.getxValueList().add(dso.getxValueList().get(0));
			rendererValue.getyValueList().add(dso.getyValueList().get(0));
		}
		rendererValue.getTypes().add(TimeChart.TYPE);
		if (type.equals("LINE")) {
			rendererValue.setApplyBackgroundGradientColor(true);
			rendererValue.setFromBackgroundGradientColor(Color.argb(200, 222, 222, 222));
			rendererValue.setToBackgroundGradientColor(Color.argb(200, 179, 179, 179));
			
			rendererValue.getColors().add(Color.rgb(13, 99, 228));
			
			if (showDSOForAllGraph) {
				rendererValue.getTitles().add("DSO For All");
				rendererValue.getSliderTextList().add("As of ");
				rendererValue.getSliderTextList().add("DSO For All: ");
				
				rendererValue.getColors().add(Color.rgb(206, 178, 0));
				
				rendererValue.getPointStyles().add(PointStyle.POINT);
				rendererValue.getxValueList().add(dso.getxValueList().get(0));
				rendererValue.getyValueList().add(dso.getyValueList().get(1));
				rendererValue.getTypes().add(TimeChart.TYPE);
			}
			if (showDSOForPriorPeriodGraph) {
				rendererValue.getTitles().add("DSO For Prior Period");
				rendererValue.getSliderTextList().add("As of ");
				rendererValue.getSliderTextList().add("DSO For Prior Period: ");
				rendererValue.getColors().add(Color.rgb(20, 135, 0));
				
				rendererValue.getPointStyles().add(PointStyle.POINT);
				rendererValue.getxValueList().add(dso.getxValueList().get(0));
				rendererValue.getyValueList().add(dso.getyValueList().get(2));
				rendererValue.getTypes().add(TimeChart.TYPE);
			}
			if (showDSOBestPossibleGraph) {
				rendererValue.getTitles().add("DSO Best Possible");
				rendererValue.getSliderTextList().add("As of ");
				rendererValue.getSliderTextList().add("DSO Best Possible: ");
				rendererValue.getColors().add(Color.rgb(185, 2, 194));
				//rendererValue.getColors().add(Color.rgb(225, 46, 35));
				rendererValue.getPointStyles().add(PointStyle.POINT);
				rendererValue.getxValueList().add(dso.getxValueList().get(0));
				rendererValue.getyValueList().add(dso.getyValueList().get(3));
				rendererValue.getTypes().add(TimeChart.TYPE);
			}
			if (showNoOfCollectorsGraph) {
				rendererValue.getTitles().add(0, "No of Collectors");
				rendererValue.getSliderTextList().add(0, "As of ");
				rendererValue.getSliderTextList().add(1, "No of Collectors: ");
				rendererValue.getyMinList().add(0d);
				rendererValue.getyMaxList().add(1000d);
				rendererValue.getColors().add(0, Color.rgb(13, 99, 228));
				rendererValue.getPointStyles().add(0, PointStyle.POINT);
				rendererValue.getxValueList().add(0, dso.getxValueList().get(0));
				rendererValue.getyValueList().add(0, dso.getyValueList().get(4));
				rendererValue.getTypes().add(0, BarChart.TYPE);
			}
		}

		if (type.equals("TIME SLIDER")) {
			rendererValue.setApplyBackgroundGradientColor(false);
			rendererValue.setFromBackgroundGradientColor(Color.rgb(114, 114, 114));
			rendererValue.setToBackgroundGradientColor(Color.rgb(114, 114, 114));
			rendererValue.getColors().add(Color.rgb(169, 169, 169));
			rendererValue.setTimeSliderXLeftScale(0.91 / (0.02 * MockDataFactory.size));
		}
		return rendererValue;
	}

	public Customer getCustomer() {
		return customer;
	}

	public void setCustomer(Customer customer) {
		this.customer = customer;
	}

	public Context getContext() {
		return context;
	}

	public void setContext(Context context) {
		this.context = context;
	}

	public boolean isShowDSOBestPossibleGraph() {
		return showDSOBestPossibleGraph;
	}

	public void setShowDSOBestPossibleGraph(boolean showDSOBestPossibleGraph) {
		this.showDSOBestPossibleGraph = showDSOBestPossibleGraph;
		this.notifyDataSetChanged();
	}

	public boolean isShowDSOForAllGraph() {
		return showDSOForAllGraph;
	}

	public void setShowDSOForAllGraph(boolean showDSOForAllGraph) {
		this.showDSOForAllGraph = showDSOForAllGraph;
		this.notifyDataSetChanged();
	}

	public boolean isShowDSOForPriorPeriodGraph() {
		return showDSOForPriorPeriodGraph;
	}

	public void setShowDSOForPriorPeriodGraph(boolean showDSOForPriorPeriodGraph) {
		this.showDSOForPriorPeriodGraph = showDSOForPriorPeriodGraph;
		this.notifyDataSetChanged();
	}

	public boolean isShowNoOfCollectorsGraph() {
		return showNoOfCollectorsGraph;
	}

	public void setShowNoOfCollectorsGraph(boolean showNoOfCollectorsGraph) {
		this.showNoOfCollectorsGraph = showNoOfCollectorsGraph;
		this.notifyDataSetChanged();
	}
}
